#ifndef INFINITY_SERVICE_WORLD_H
#	define INFINITY_SERVICE_WORLD_H

#include "service.h"

#include "planet.h"
#include "worldsector.h"
#include "worldarea.h"

#include "shapes.h"

namespace infinity {

class ServiceWorld
:	public Service
{
public : //! @name Constants
	//! @{
	static const ServiceKey Key;

	static const dw::uint32 MaxCachedSectors = 512;
	static const dw::uint32 MaxCachedSectorsPerUpdate = 8;
	//! @}

public : //! @name Types definitions
	//! @{
	typedef Service super;

	class AreaOfInterest
	{
	public : //! @name Types definitions
		//! @{
		typedef AABBox< dw::int32, 3 > CellsBox;
		//! @}

		/*
	public : //! @name Commands
		//! @{
		virtual void updateRequiredSectors() = 0;
		//! @}
		*/

	public : //! @name State
		//! @{
		virtual void getAABBox(CellsBox& aabb) const = 0;
		virtual dw::float32 getPriority(const CellsBox& aabb) const = 0;
		//! @}
	};
	//! @}

public : //! @name Commands
	//! @{
	void registerAreaOfInterest(const AreaOfInterest* area);
	void unregisterAreaOfInterest(const AreaOfInterest* area);
	//! @}

public : //! @name Service overrides
	//! @{
	void renderDebug();
	//! @}

protected : //! @name Service callbacks
	//! @{
	virtual State onInitializeSimulation();
	virtual void onUpdateSimulation(dw::float32 deltaT);
	virtual State onTerminateSimulation();
	//! @}

private : //! @name Construction & Destruction
	//! @{
	friend class ServiceManager;

	ServiceWorld();
	virtual ~ServiceWorld();
	//! @}

private : //! @name Types definitions
	//! @{
	struct SectorPriorityComp
	{
	public :
		bool operator() (const WorldSector* lhs, const WorldSector* rhs) const
		{
			return lhs->priority < rhs->priority;
		}
	};
	struct SectorAgeComp
	{
	public :
		bool operator() (const WorldSector* lhs, const WorldSector* rhs) const
		{
			return lhs->age > rhs->age;
		}
	};

	typedef std::vector< WorldSector* > SectorsLRUQueue;
	typedef std::vector< WorldSector* > SectorsCacheQueue;
	typedef std::vector< WorldArea* > AreasCollection;
	typedef std::queue< WorldSector* > FreeSectorsCollection;
	typedef std::vector< const AreaOfInterest* > AreasOfInterestCollection;
	//! @}

private : //! @name Helpers
	//! @{
	void initializeAreas();
	void initializeSectors();

	WorldArea* getArea(const Vector3i& areaId);
	//! @}

private : //! @name Data
	//! @{
	Planet* m_planet;

	AreasCollection m_areas;
	Vector3i m_areasCount;

	WorldSector* m_sectors;
	dw::uint32 m_sectorsCount;

	SectorsLRUQueue m_lruSectors;
	FreeSectorsCollection m_freeSectors;

	SectorsCacheQueue m_cache;

	AreasOfInterestCollection m_areasOfInterest;
	//! @}
};

} // namespace infinity

#include "serviceworld.inl"

#endif // !INFINITY_SERVICE_WORLD_H
